﻿using System;
using System.Diagnostics;
using System.Windows.Input;
using SimpleDbBrowser.ViewModel.Properties;

namespace SimpleDbBrowser.ViewModel
{
    /// <summary>
    /// The view model describing the options for the simpledb browser.
    /// </summary>
    public sealed class OptionsViewModel : ViewModelBase, ICommittableViewModel
    {
        private string accessKey;
        private string secretKey;
        private string proxyHost;
        private int proxyPort;
        private bool enableConnectionSettings;

        /// <summary>
        /// Initializes a new instance of the OptionsViewModel class based on 
        /// the currently saved settings.
        /// </summary>
        public OptionsViewModel()
        {
            Debug.WriteLine("Creating OptionsViewModel");

            this.Commit = new RelayCommand(this.OnSaveConfiguration, this.CanSaveConfiguration);

            this.accessKey = Settings.Default.AWSAccessKey;
            this.secretKey = Settings.Default.AWSSecretKey;
            this.ProxyPort = Settings.Default.ProxyPort;
            this.ProxyHost = Settings.Default.ProxyHost;
            this.EnableConnectionSettings = Settings.Default.ManualProxyConfig;
        }

        /// <summary>
        /// Gets or sets the SimpleDB access key.
        /// </summary>
        public string AccessKey
        {
            get { return this.accessKey; }

            set
            {
                if (this.accessKey == value) return;

                this.accessKey = value;
                this.OnPropertyChanged("AccessKey");
                Debug.WriteLine(string.Format("OptionsViewModel.AccessKey set to {0}", this.accessKey));
            }
        }

        /// <summary>
        /// Gets or sets the SimpleDB secret key.
        /// </summary>
        public string SecretKey
        {
            get { return this.secretKey; }

            set
            {
                if (this.secretKey == value) return;

                this.secretKey = value;
                this.OnPropertyChanged("SecretKey");
                Debug.WriteLine(string.Format("OptionsViewModel.SecretKey set to {0}", this.secretKey));
            }
        }

        /// <summary>
        /// Gets or sets the proxy host to use.
        /// </summary>
        public string ProxyHost
        {
            get { return this.proxyHost; }

            set
            {
                if (this.proxyHost == value) return;

                this.proxyHost = value;
                this.OnPropertyChanged("ProxyHost");
                Debug.WriteLine(string.Format("OptionsViewModel.ProxyHost set to {0}", this.proxyHost));
            }
        }

        /// <summary>
        /// Gets or sets the proxy port to use.
        /// </summary>
        public int ProxyPort
        {
            get { return this.proxyPort; }
            
            set
            {
                if (this.proxyPort == value) return;

                this.proxyPort = value;
                this.OnPropertyChanged("ProxyPort");
                Debug.WriteLine(string.Format("OptionsViewModel.ProxyPort set to {0}", this.proxyPort));
            }
        }

        /// <summary>
        /// Gets the UI-friendly name of the options view model.
        /// </summary>
        public override string DisplayName
        {
            get
            {
                return "SimpleDB Browser Options";
            }
            
            protected set
            {
                throw new NotSupportedException();
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the proxy settings should be enabled.
        /// </summary>
        public bool EnableConnectionSettings
        {
            get { return this.enableConnectionSettings; }
            
            set
            {
                if (this.enableConnectionSettings == value) return;

                this.enableConnectionSettings = value;
                this.OnPropertyChanged("EnableConnectionSettings");
                Debug.WriteLine(string.Format("OptionsViewModel.EnableConnectionSettings set to {0}", this.enableConnectionSettings));
            }
        }

        public ICommand Commit { get; private set; }

        /// <summary>
        /// The configuration that was set up.
        /// </summary>
        public AwsConfiguration Configuration { get; private set; }

        /// <summary>
        /// Executes the SaveConfiguration command.
        /// </summary>
        /// <param name="o">
        /// This is not used.
        /// </param>
        private void OnSaveConfiguration(object o)
        {
            this.Configuration = new AwsConfiguration(this.accessKey, this.secretKey, this.enableConnectionSettings, this.proxyHost, this.proxyPort);
            Settings.Default.AWSAccessKey = this.accessKey;
            Settings.Default.AWSSecretKey = this.secretKey;
            Settings.Default.ProxyHost = this.proxyHost;
            Settings.Default.ProxyPort = this.proxyPort;
            Settings.Default.ManualProxyConfig = this.enableConnectionSettings;
            Settings.Default.Save();
            this.OnPropertyChanged("Configuration");
        }

        /// <summary>
        /// Determines whether the SaveConfiguration command can be executed.
        /// </summary>
        /// <param name="o">
        /// This is not used.
        /// </param>
        /// <returns>
        /// True if the command can be executed, otherwise false.
        /// </returns>
        private bool CanSaveConfiguration(object o)
        {
            var accessKeysChanged = this.accessKey != Settings.Default.AWSAccessKey || this.secretKey != Settings.Default.AWSSecretKey;
            var manualProxyChanged = this.enableConnectionSettings != Settings.Default.ManualProxyConfig;
            var proxyConfigChanged = this.proxyHost != Settings.Default.ProxyHost || this.proxyPort != Settings.Default.ProxyPort;

            return (accessKeysChanged || manualProxyChanged || (proxyConfigChanged && this.enableConnectionSettings));
        }
    }
}
